home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / programer2 / icon / Source / Icont / C / Tmain < prev    next >
Encoding:
Text File  |  1990-07-20  |  13.3 KB  |  569 lines

  1. /*
  2.  * tmain.c - main program for translator and linker.
  3.  */
  4.  
  5. #include "../h/config.h"
  6. #include "general.h"
  7. #include "tproto.h"
  8. #include "../h/paths.h"
  9.  
  10. /*
  11.  * Prototypes.
  12.  */
  13.  
  14. hidden    novalue    execute    Params((char *ofile,char *efile,char * *args));
  15. hidden    novalue    report Params((char *s));
  16. hidden    novalue    rmfiles Params((char **p));
  17. hidden    novalue    usage Params((noargs));
  18.  
  19. /*
  20.  * The following code is operating-system dependent [@tmain.01].  Include
  21.  *  files and such.
  22.  */
  23.  
  24. #if PORT
  25. Deliberate syntax error
  26. #endif                    /* PORT */
  27.  
  28. #if AMIGA || ARM || HIGHC_386 || MSDOS || MVS || UNIX || VM || VMS
  29. /* nothing is needed */
  30. #endif                    /* AMIGA || HIGHC_386 || ... */
  31.  
  32. #if ATARI_ST
  33. char *patharg;
  34. #endif                    /* ATARI_ST */
  35.  
  36. #if MACINTOSH
  37. #if MPW
  38. #include <fcntl.h>    /* MPW3 - for unlink() */
  39. #include <CursorCtl.h>
  40. void SortOptions();
  41. #endif                    /* MPW */
  42. #endif                    /* MACINTOSH */
  43.  
  44. #if OS2
  45. #include <process.h>
  46. #endif                    /* OS2 */
  47. /*
  48.  * End of operating-system specific code.
  49.  */
  50.  
  51. #if IntBits == 16
  52. #ifdef strlen
  53. #undef strlen                /* pre-defined in some contexts */
  54. #endif                    /* strlen */
  55. #endif                    /* Intbits == 16 */
  56.  
  57. #ifndef Iconx
  58. #define Iconx IconxPath
  59. #endif                    /* Iconx */
  60.  
  61. /*
  62.  *  Define global variables.
  63.  */
  64.  
  65. #define Global
  66. #define Init(v) = v
  67. #include "globals.h"
  68.  
  69. char *ofile = NULL;            /* linker output file name */
  70.  
  71. /*
  72.  * getopt() variables
  73.  */
  74. extern int optind;        /* index into parent argv vector */
  75. extern int optopt;        /* character checked for validity */
  76. extern char *optarg;        /* argument associated with option */
  77.  
  78. /*
  79.  *  main program
  80.  */
  81. novalue main(argc,argv)
  82. int argc;
  83. char **argv;
  84.    {
  85.    int nolink = 0;            /* suppress linking? */
  86.    int errors = 0;            /* translator and linker errors */
  87.    char **tfiles, **tptr;        /* list of files to translate */
  88.    char **lfiles, **lptr;        /* list of files to link */
  89.    char **rfiles, **rptr;        /* list of files to remove */
  90.    char *efile = NULL;            /* stderr file */
  91.    char buf[MaxFileName];        /* file name construction buffer */
  92.    int c, n;
  93.    struct fileparts *fp;
  94.  
  95. #if MACINTOSH
  96. #if MPW
  97.    InitCursorCtl(NULL);
  98.    SortOptions(argv);
  99. #endif                    /* MPW */
  100. #endif                    /* MACINTOSH */
  101.  
  102.    /*
  103.     * Process options.
  104.     */
  105.    while ((c = getopt(argc,argv,Options)) != EOF)
  106.       switch (c) {
  107.          case 'c':            /* -c: compile only (no linking) */
  108.             nolink = 1;
  109.             break;
  110.          case 'e':            /* -e file: redirect stderr */
  111.             efile = optarg;
  112.             break;
  113.          case 'm':            /* -m: preprocess using m4(1) [UNIX] */
  114.             m4pre = 1;
  115.             break;
  116.          case 'o':            /* -o file: name output file */
  117.             ofile = optarg;
  118.             break;
  119.  
  120. #if ATARI_ST
  121.          case 'p':            /* -p path: iconx path [ATARI] */
  122.             patharg = optarg;
  123.             break;
  124. #endif                    /* ATARI_ST */
  125.  
  126.          case 's':            /* -s: suppress informative messages */
  127.             silent = 1;
  128.             break;
  129.          case 'u':            /* -u: warn about undeclared ids */
  130.             uwarn = 1;
  131.             break;
  132.          case 't':            /* -t: turn on procedure tracing */
  133.             trace = -1;
  134.             break;
  135.  
  136.  
  137.          case 'L':            /* -L: enable linker debugging */
  138.  
  139. #ifdef DeBugLinker
  140.             Dflag = 1;
  141. #endif                    /* DeBugLinker */
  142.  
  143.             break;
  144.  
  145.          case 'S':            /* -Sxnnnn: set a size */
  146.             sizearg(optarg,argv);
  147.             break;
  148.          default:
  149.          case 'x':            /* -x illegal until after file list */
  150.             usage();
  151.          }
  152.  
  153.    /*
  154.     * Allocate space for lists of file names.
  155.     */
  156.    n = argc - optind + 1;
  157.    tptr = tfiles = (char **)alloc((unsigned int)(n * sizeof(char *)));
  158.    lptr = lfiles = (char **)alloc((unsigned int)(n * sizeof(char *)));
  159.    rptr = rfiles = (char **)alloc((unsigned int)(2 * n * sizeof(char *)));
  160.  
  161.    /*
  162.     * Scan file name arguments.
  163.     */
  164.    while (optind < argc)  {
  165.       if (strcmp(argv[optind],"-x") == 0)    /* stop at -x */
  166.          break;
  167.       else if (strcmp(argv[optind],"-") == 0) {
  168. #if ARM
  169.     /* Different file naming, so we need a different strategy... */
  170.     *tptr++ = "-";
  171.     /* Use makename(), pretending we had an input file named "Stdin" */
  172.     makename(buf,TargetDir,"Stdin",U1Suffix);
  173.     *lptr++ = *rptr++ = salloc(buf);    /* link & remove .u1 */
  174.     makename(buf,TargetDir,"Stdin",U2Suffix);
  175.     *rptr++ = salloc(buf);        /* also remove .u2 */
  176.  
  177. #else                    /* ARM */
  178.  
  179.          *tptr++ = "-";                /* "-" means standard input */
  180.          *lptr++ = *rptr++ = "stdin.u1";
  181.          *rptr++ = "stdin.u2";
  182. #endif
  183.          }
  184.       else {
  185.          fp = fparse(argv[optind]);        /* parse file name */
  186.          if (*fp->ext == '\0' || smatch(fp->ext, SourceSuffix)) {
  187.             makename(buf,SourceDir,argv[optind], SourceSuffix);
  188.             *tptr++ = salloc(buf);        /* translate the .icn file */
  189.             makename(buf,TargetDir,argv[optind],U1Suffix);
  190.             *lptr++ = *rptr++ = salloc(buf);    /* link & remove .u1 */
  191.             makename(buf,TargetDir,argv[optind],U2Suffix);
  192.             *rptr++ = salloc(buf);        /* also remove .u2 */
  193.             }
  194.          else if (smatch(fp->ext,U1Suffix) || smatch(fp->ext,U2Suffix)
  195.                || smatch(fp->ext,USuffix)) {
  196.             makename(buf,TargetDir,argv[optind],U1Suffix);
  197.             *lptr++ = salloc(buf);
  198.             }
  199.          else
  200.             quitf("bad argument %s",argv[optind]);
  201.          }
  202.       optind++;
  203.       }
  204.  
  205.    *tptr = *lptr = *rptr = NULL;    /* terminate filename lists */
  206.    if (lptr == lfiles)
  207.       usage();                /* error -- no files named */
  208.  
  209.    /*
  210.     * Round hash table sizes to next power of two, and set masks for hashing.
  211.     */
  212.    chsize = round2(chsize);  cmask = chsize - 1;
  213.    fhsize = round2(fhsize);  fmask = fhsize - 1;
  214.    ghsize = round2(ghsize);  gmask = ghsize - 1;
  215.    ihsize = round2(ihsize);  imask = ihsize - 1;
  216.    lhsize = round2(lhsize);  lmask = lhsize - 1;
  217.  
  218.    /*
  219.     * Translate .icn files to make .u1 and .u2 files.
  220.     */
  221.    if (tptr > tfiles) {
  222.       if (!silent)
  223.          report("Translating");
  224.       errors = trans(tfiles);
  225.       if (errors > 0)            /* exit if errors seen */
  226.          exit(ErrorExit);
  227.       }
  228.  
  229.    /*
  230.     * Link .u1 and .u2 files to make an executable.
  231.     */
  232.    if (nolink)                /* exit if no linking wanted */
  233.  
  234. #if MACINTOSH
  235. #if MPW
  236.       /*
  237.        *  Set type of translator output ucode (.u) files
  238.        *  to 'TEXT', so they can be easily viewed by editors.
  239.        */
  240.       {
  241.       char **p;
  242.       void setfile();
  243.       for (p = rfiles; *p; ++p)
  244.          setfile(*p,'TEXT','icon');
  245.       }
  246. #endif                    /* MPW */
  247. #endif                    /* MACINTOSH */
  248.  
  249.       exit(NormalExit);
  250.  
  251.    if (ofile == NULL)  {        /* if no -o file, synthesize a name */
  252.       ofile = salloc(makename(buf,TargetDir,lfiles[0],IcodeSuffix));
  253.    } else {                /* add extension in necessary */
  254.       fp = fparse(ofile);
  255.  
  256. #if !(MACINTOSH && MPW) /* This code provokes code generation bug in */
  257.         /* pre-release MPW 3.0 C compiler */
  258.       if (*fp->ext == '\0' && *IcodeSuffix != '\0') /* if no ext given, but wanted */
  259.          ofile = salloc(makename(buf,TargetDir,ofile,IcodeSuffix));
  260. #endif                    /* !(MACINTOSH && MPW) */
  261.  
  262.       if (*fp->ext == '\0' && *IcodeSuffix != '\0') /* if no ext given */
  263.          ofile = salloc(makename(buf,TargetDir,ofile,IcodeSuffix));
  264.    }
  265.  
  266.    if (!silent)
  267.       report("Linking");
  268.    errors = ilink(lfiles,ofile);    /* link .u files to make icode file */
  269.  
  270.    /*
  271.     * Finish by removing intermediate files.
  272.     *  Execute the linked program if so requested and if there were no errors.
  273.     */
  274.  
  275. #if MACINTOSH
  276. #if MPW
  277.    /* Set file type to TEXT so it will be executable as a script. */
  278.    setfile(ofile,'TEXT','icon');
  279. #endif                    /* MPW */
  280. #endif                    /* MACINTOSH */
  281.  
  282.    rmfiles(rfiles);            /* remove intermediate files */
  283.    if (errors > 0) {            /* exit if linker errors seen */
  284.       unlink(ofile);
  285.       exit(ErrorExit);
  286.       }
  287.  
  288.    if (optind < argc)  {
  289.       if (!silent)
  290.          report("Executing");
  291.       execute (ofile, efile, argv+optind+1);
  292.       }
  293.  
  294.    exit(NormalExit);
  295.    }
  296.  
  297. /*
  298.  * execute - execute iconx to run the icon program
  299.  */
  300. static novalue execute(ofile,efile,args)
  301. char *ofile, *efile, **args;
  302.    {
  303.    int n;
  304.    char **argv, **p;
  305.  
  306.    for (n = 0; args[n] != NULL; n++)    /* count arguments */
  307.       ;
  308.    p = argv = (char **)alloc((unsigned int)((n + 5) * sizeof(char *)));
  309.  
  310.    *p++ = Iconx;            /* set iconx pathname */
  311.    if (efile != NULL) {            /* if -e given, copy it */
  312.       *p++ = "-e";
  313.       *p++ = efile;
  314.       }
  315.    *p++ = ofile;            /* pass icode file name */
  316.  
  317. #if AMIGA && LATTICE
  318.    *p = *args;
  319.    while (*p++) {
  320.       *p = *args;
  321.       args++;
  322.    }
  323. #else                    /* AMIGA && LATTICE */
  324.    while (*p++ = *args++)        /* copy args into argument vector */
  325.       ;
  326. #endif                    /* AMIGA && LATTICE */
  327.  
  328.    *p = NULL;
  329.  
  330. /*
  331.  * The following code is operating-system dependent [@tmain.02].  It calls
  332.  *  iconx on the way out.
  333.  */
  334.  
  335. #if PORT
  336.    /* something is needed */
  337. Deliberate Syntax Error
  338. #endif                    /* PORT */
  339.  
  340. #if ARM
  341.     {
  342.         int i = 7 + strlen(Iconx);
  343.         int j;
  344.         char *s;
  345.         char buffer[255];
  346.         extern int armquote(char *, char **);
  347.  
  348.         sprintf(buffer, "Chain:%s ", Iconx);
  349.         for (p = argv + 1; *p; ++p)
  350.         {
  351.             j = armquote(*p, &s);
  352.  
  353.             if (j == -1 || i + j >= 255)
  354.             {
  355.                 fprintf(stderr, "Cannot execute: command line too long");
  356.                 fflush(stderr);
  357.                 return;
  358.             }
  359.  
  360.             strcpy(buffer + i, s);
  361.             i += j;
  362.             buffer[i] = ' ';
  363.         }
  364.         buffer[i] = '\0';
  365.         system(buffer);
  366.     }
  367. #endif                    /* ARM */
  368.  
  369. #if AMIGA
  370. #if AZTEC_C
  371.       execvp(Iconx,argv);
  372.       return;
  373. #endif                    /* AZTEC_C */
  374. #if LATTICE
  375.       {
  376.       struct ProcID procid;
  377.       if (forkv(Iconx,argv,NULL,&procid) == 0) { 
  378.          wait(&procid);
  379.          return;
  380.          }
  381.       }
  382. #endif                    /* LATTICE */
  383. #endif                    /* AMIGA */
  384.  
  385. #if ATARI_ST || MVS || VM
  386.       /* Forkvp(Iconx,argv); */
  387.       /* return; */
  388.       fprintf(stderr,"-x not supported\n");
  389.       fflush(stderr);
  390.      /* not implemented yet */
  391. #endif                    /* ATARI_ST || MVS || VM */
  392.  
  393. #if HIGHC_386
  394.       fprintf(stderr,"-x not supported\n");
  395.       fflush(stderr);
  396.      /* not implemented yet */
  397. #endif                    /* HIGHC_386 */
  398.  
  399. #if MACINTOSH
  400. #if MPW
  401.       /*
  402.        *  Something slightly different ...
  403.        */
  404.       {
  405.       char *s;
  406.       char *mpwquote();
  407.  
  408.       fputs(Iconx,stdout);
  409.       for (p = argv + 1; *p; ++p) {
  410.          putchar(' ');
  411.      fputs(s = mpwquote(*p),stdout);
  412.      free(s);
  413.      }
  414.       putchar('\n');
  415.       return;
  416.       }
  417. #endif                    /* MPW */
  418. #if LSC
  419.       fprintf(stderr,"-x not supported\n");
  420.       fflush(stderr);
  421. #endif                    /* LSC */
  422. #endif                    /* MACINTOSH */
  423.  
  424. #if MSDOS
  425. #if LATTICE || MICROSOFT || TURBO
  426.       execvp(Iconx,argv);    /* execute with path search */
  427. #endif                    /* LATTICE || MICROSOFT || TURBO */
  428. #if MWC
  429.       fprintf(stderr,"-x not supported\n");
  430.       fflush(stderr);
  431.       /* execall(Iconx,argv); */
  432. #endif                    /* MWC */
  433. #endif                    /* MSDOS */
  434.  
  435. #if MVS || VM
  436. #if SASC
  437.       exit(sysexec(Iconx, argv));
  438. #endif                    /* SASC */
  439. #endif                                  /* MVS || VM */
  440.  
  441. #if OS2
  442.       execvp(Iconx,argv);    /* execute with path search */
  443. #endif                    /* OS2 */
  444.  
  445. #if UNIX
  446.       /*
  447.        * If an ICONX environment variable is defined, use that.
  448.        *  If not, first try the predefined path, then search $PATH via execvp. 
  449.        */
  450.       if ((argv[0] = getenv("ICONX")) != NULL && argv[0][0] != '\0') {
  451.          execv(argv[0], argv);    /* exec file specified by $ICONX */
  452.          quitf("cannot execute $ICONX (%s)", argv[0]);
  453.          }
  454.  
  455. #ifdef HardWiredPaths
  456. #ifdef CRAY
  457.       argv[0] = "iconx";
  458.       execv(Iconx, argv);
  459. #else                    /* CRAY */
  460.       argv[0] = Iconx;        /* try predefined file */
  461.       execv(argv[0], argv);
  462. #endif                    /* CRAY */
  463. #endif                    /* HardWiredPaths */
  464.  
  465.       argv[0] = "iconx";
  466.       execvp(argv[0], argv);    /* if no Iconx, search path for "iconx" */
  467.  
  468. #ifdef HardWiredPaths
  469.       quitf("cannot run %s", Iconx);
  470. #else                    /* HardWiredPaths */
  471.       quitf("cannot find iconx", "");
  472. #endif                    /* HardWiredPaths */
  473. #endif                    /* UNIX */
  474.  
  475. #if VMS
  476.       execv(Iconx,argv);
  477. #endif                    /* VMS */
  478.  
  479. /*
  480.  * End of operating-system specific code.
  481.  */
  482.  
  483.    quitf("could not run %s",Iconx);
  484.    }
  485.  
  486. static novalue report(s)
  487. char *s;
  488.    {
  489.  
  490. /*
  491.  * The following code is operating-system dependent [@tmain.03].  Report
  492.  *  phase.
  493.  */
  494.  
  495. #if PORT
  496.    fprintf(stderr,"%s:\n",s);
  497. Deliberate Syntax Error
  498. #endif                    /* PORT */
  499.  
  500. #if AMIGA || ARM || ATARI_ST || HIGHC_386 || MSDOS || MVS || OS2 || UNIX || VM || VMS
  501.    fprintf(stderr,"%s:\n",s);
  502. #endif                    /* AMIGA || ATARI_ST || HIGHC_386 ... */
  503.  
  504. #if MACINTOSH
  505. #if MPW
  506.    printf("Echo '%s:' > Dev:StdErr\n",s);
  507. #endif                    /* MPW */
  508. #if LSC
  509.    fprintf(stderr,"%s:\n",s);
  510. #endif                    /* LSC */
  511. #endif                    /* MACINTOSH */
  512.  
  513. /*
  514.  * End of operating-system specific code.
  515.  */
  516.  
  517.    }
  518.  
  519. /*
  520.  * rmfiles - remove a list of files
  521.  */
  522.  
  523. static novalue rmfiles(p)
  524. char **p;
  525.    {
  526.    for (; *p; p++) {
  527. /*
  528.  * The following code is operating-system dependent [@tmain.04].
  529.  *  remove files.
  530.  */
  531.  
  532. #if PORT
  533.       unlink(*p);
  534. Deliberate Syntax Error
  535. #endif                    /* PORT */
  536.  
  537. #if AMIGA || ARM || ATARI_ST || HIGHC_386 || MSDOS || MVS || OS2 || UNIX || VM || VMS
  538.       unlink(*p);
  539. #endif                    /* AMIGA || ATARI_ST ... */
  540.  
  541. #if MACINTOSH
  542. #if MPW
  543.       /*
  544.        * MPW generates commands rather than doing the actions
  545.        *  at this time.
  546.        */
  547.       fprintf(stdout,"Delete %s\n", *p);
  548. #endif                    /* MPW */
  549. #if LSC
  550.       unlink(*p);
  551. #endif                    /* LSC */
  552. #endif                    /* MACINTOSH */
  553.  
  554. /*
  555.  * End of operating-system specific code.
  556.  */
  557.       }
  558.    }
  559.  
  560. /*
  561.  * Print an error message if called incorrectly.  The message depends
  562.  *  on the legal options for this system.
  563.  */
  564. static novalue usage()
  565.    {
  566.    fprintf(stderr,"usage: %s %s file ... [-x args]\n", progname, Usage);
  567.    exit(ErrorExit);
  568.    }
  569.